#factory
n = Node( "core", "Node" )
assert 'Node' == n.type

#tree
child = Node( "core", "Node" )

n.addChild( child )
assert n == child.parent
assert n.hasChild( child )
assert [ child ] == n.children
n.removeChild( child )
assert not n.hasChild( child )
assert [] == n.children
assert None == child.parent

child.attachToParent( n )
assert n == child.parent
assert n.hasChild( child )
assert [ child ] == n.children
child.detachFromParent()
assert None == child.parent
assert not n.hasChild( child )
assert [] == n.children

#node subclass

@node( "pytest" )
class PyTestNode:
  def __init__( self ):
    self.i = 0
    self.jval = 0
  
  def foo( self, i ):
    self.i = i
    
  def bar( self ):
    return self.i
    
  def set_j( self, j ):
    self.jval = j
    
  def get_j( self ):
    return self.jval
    
  def get_k( self ):
    return 3
    
testNode = Node( "pytest", 'PyTestNode' )
assert testNode.module == "pytest"
assert testNode.type == 'PyTestNode'

assert 0 == testNode.i
testNode.i = -1
assert -1 == testNode.i

assert -1 == testNode.bar()
testNode.foo( 1 )
assert 1 == testNode.bar()

assert 0 == testNode.j
testNode.j = 2
assert 2 == testNode.j

assert 3 == testNode.k

#math

def eq( d1, d2 ):
  return abs( d1 - d2 ) < 1e-5

import math
rr = Rot2d.fromRadians( math.pi )
assert eq( 180, rr.degrees() )
assert eq( math.pi, rr.radians() )
rd = Rot2d.fromDegrees( 180 )
assert eq( 180, rd.degrees() )
assert eq( math.pi, rd.radians() )
assert rr == rd
assert Rot2d.fromDegrees( 90 ) + Rot2d.fromRadians( math.pi / 4 ) == Rot2d.fromDegrees( 135 )
assert Rot2d.fromDegrees( 180 ) - Rot2d.fromDegrees( 90 ) == Rot2d.fromRadians( math.pi / 2 )
assert Rot2d.fromDegrees( -45 ) == Rot2d.fromDegrees( 45 ).inverse()

v = Vec2d( 1, 2 )
assert v == v
assert 1 == v.x
assert 2 == v.y
t = Vec2d( 3, 4 )
assert Vec2d( v.x + t.x, v.y + t.y ) == v + t
assert Vec2d( v.x - t.x, v.y - t.y ) == v - t
assert Vec2d( v.x * t.x, v.y * t.y ) == v * t
assert Vec2d( v.x / t.x, v.y / t.y ) == v / t
assert Vec2d( v.x * 3, v.y * 3 ) == v * 3
assert Vec2d( v.x / 2, v.y / 2 ) == v / 2
assert t.squaredLength() == 25
assert t.length() == 5
assert Vec2d( 0, 1 ).toRot() == Rot2d.fromDegrees( 90 )
assert Vec2d( 10, 0 ).normalize() == Vec2d( 1, 0 )
assert Vec2d( 20, 10 ).dot( Vec2d( 1, 2 ) ) == 40

axis = Vec3d( 1, 2, 3 )
angle = 0.45
r = Rot3d( axis, angle )
assert axis.normalize(), angle == r.toAxisAngle()
assert Vec3d( 0, 1, 0 ) == Rot3d( Vec3d( 0, 0, 1 ), math.pi / 2. ) * Vec3d( 1, 0, 0 )
assert Rot3d( Vec3d( 0, 0, 1 ), math.pi / 4. ) == Rot3d( Vec3d( 0, 0, -1 ), math.pi / 4. ).inverse()

v = Vec2d( 1, 2 )
t = Vec2d( 3, 4 )
r = Rot2d.fromDegrees( 5 )
s = Vec2d( 5, 6 )
mt = Mat2d.translation( t )
mr = Mat2d.rotation( r )
ms = Mat2d.scale( s )
assert t == mt.getTranslation()
assert r == mr.getRotation()
assert s == ms.getScale()
assert v == Mat2d() * v
assert v + t == mt * v
assert v * r == mr * v
assert v * s == ms * v
assert s * ( ( t + v ) * r ) == ms * ( mr * ( mt * v ) )
assert s * ( ( t + v ) * r ) == ( ms * mr * mt ) * v
mti = mt.inverse()
mri = mr.inverse()
msi = ms.inverse()
ri = r.inverse()
assert v == v * r * ri
assert v - t == mti * v
assert v * ri == mri * v
assert v / s == msi * v
assert ( ( v - t ) * ri ) / s == msi * ( mri * ( mti * v ) )
assert ( ( v - t ) * ri ) / s == ( msi * mri * mti ) * v

v = Vec3d( 1, 2, 3 )
t = Vec3d( 3, 4, 5 )
r = Rot3d( Vec3d( -1, -2, -3 ), -.4 )
s = Vec3d( 5, 6, 7 )
mt = Mat3d.translation( t )
mr = Mat3d.rotation( r )
ms = Mat3d.scale( s )
assert t == mt.getTranslation()
assert r == mr.getRotation()
assert s == ms.getScale()
assert v == Mat3d() * v
assert v + t == mt * v
assert v * r == mr * v
assert v * s == ms * v
assert s * ( ( t + v ) * r ) == ms * ( mr * ( mt * v ) )
assert s * ( ( t + v ) * r ) == ( ms * mr * mt ) * v
mti = mt.inverse()
mri = mr.inverse()
msi = ms.inverse()
ri = r.inverse()
assert v == v * r * ri
assert v - t == mti * v
assert v * ri == mri * v
assert v / s == msi * v
assert ( ( v - t ) * ri ) / s == msi * ( mri * ( mti * v ) )
assert ( ( v - t ) * ri ) / s == ( msi * mri * mti ) * v
